#!/bin/bash -e
#
#   Neutron3529's Unity Game Plugin
#   Copyright (C) 2022-2023 Neutron3529
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU Affero General Public License as
#   published by the Free Software Foundation, either version 3 of the
#   License, or (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU Affero General Public License for more details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
############################################################################
#
#   * compile instructions: put this file and `utils.cs` in `steamapps`
#   * folder, open a terminal in the same folder, and execute:
#   *
#   * ```
#   *     chmod +x ${file}.cs
#   *     ./${file}.cs
#   * ```
#   *
#   * then the mod will be compiled automatically.
#   *
#   * Here we wrote a shebang like file, which is correct
#   * in my computer (Manjaro XFCE), if such script do not work
#   * in your computer, you could just try the instructions below :

export GAME_NAME="${0%\.cs}"                                # might modify if the name mismatch.
export GAME_DIR="$GAME_NAME"                                # might be modified, but "$GAME_NAME" cover most of the cases.

export FILE_NAME="$0"
export ASSEMBLY="Mafi"                           # might be modified
export UTILS="utils.cs"                                     # might be modified if you do not put utils.cs in the current dir.
export PLUGIN_ID="Neutron3529.Cheat"                        # should be modified
export NAMESPACE_ID="Neutron3529.Cheat"                     # should be modified
export GAME_BASE_DIR="common/$GAME_DIR"                     # should modify GAME_DIR instead since GAME_DIR == GAME_NAME is almost always true.

export IFS=$'\n' # to disable the annoying space.
export DOTNET="dotnet" # the location of the DOTNET executable file.
[ -z "$DOTNET_CSC_DLL" ] && export DOTNET_CSC_DLL=`\ls /usr/share/dotnet/sdk/*/Roslyn/bincore/csc.dll` # In manjaro, the csc.dll is located in /usr/share/dotnet/sdk/*/Roslyn/bincore/csc.dll

case $1 in
    V)       EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
    v)       EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
    VERBOSE) EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
    verbose) EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
    D)       EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
    d)       EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
    DEBUG)   EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
    debug)   EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
    *)       EXTRA_DEFINE=""                                               ;;
esac

_MODE__SELECT_=100

( yes "" | head -n $_MODE__SELECT_ | head -n-1  ; tail $FILE_NAME -n+$_MODE__SELECT_) | sed s/%%NAMESPACE_ID%%/${NAMESPACE_ID}/g | sed s/%%PLUGIN_ID%%/${PLUGIN_ID}/g | $DOTNET $DOTNET_CSC_DLL -nologo -t:library \
  -r:"${GAME_BASE_DIR}/BepInEx/core/BepInEx.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/core/0Harmony.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/core/BepInEx.Harmony.dll" \
  `[ -e "${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/netstandard.dll" ] && echo "-r:\"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/netstandard.dll\""` \
  -r:"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/System.dll" \
  -r:"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/System.Core.dll" \
  -r:"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/UnityEngine.dll" \
  -r:"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/UnityEngine.AIModule.dll" \
  -r:"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/UnityEngine.CoreModule.dll" \
  -r:"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/UnityEngine.UI.dll" \
  -r:"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/mscorlib.dll" \
  $(for i in "${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/$ASSEMBLY"*.dll ; do echo -e "-r:\"$i\"\n" ; done) \
  -out:"${GAME_BASE_DIR}/BepInEx/plugins/${FILE_NAME%.*}".dll \
  -optimize $EXTRA_DEFINE \
  - $UTILS && rm -f "${GAME_BASE_DIR}/BepInEx/config/${PLUGIN_ID}.cfg";

if [ -n "$2" ]; then
    git add ${FILE_NAME}
    case $2 in
        R) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        r) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        RANDOM) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        random) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        U) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        u) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        UPLOAD) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        upload) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        *) git commit -am "$2" ;;
    esac
    git push
fi
exit





using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;

using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

namespace %%NAMESPACE_ID%%;

[BepInPlugin("%%PLUGIN_ID%%", "%%NAMESPACE_ID%%", "0.1.0")]
public class Cheat : Neutron3529.ModEntry {
    public Cheat() : base("%%PLUGIN_ID%%") {}
    public new void Awake() {
        logger("叮~修改器正在启动，请。。");
        patch.self=this;
        harmony.Patch(typeof(Mafi.Core.Mods.ModsLoader).GetMethod("LoadAllModsFrom",(BindingFlags)(-1)), null, new HarmonyMethod(SymbolExtensions.GetMethodInfo(() => patch.Postfix())));
        // Mafi.Localization.LocalizationManager.EnableLocalization(); // 不知道为什么不加这一句会导致游戏变成纯英文
        // 主要逻辑放在`utils.cs`中，这里的Awake2只是为了以防万一
        // 目前来说，这个函数的唯一用途是用来“叮”……
        // 就像这样：
        logger("叮~修改器启动，请安心游戏");
    }
    // [HarmonyPatch(typeof(Mafi.Unity.InputControl.GameMenu.IGameMenuController).Assembly.GetType("LocalizationSettings",true),"ApplyCurrentLanguage")]
    class patch {
        public static Cheat self;
        public static void Postfix()=>(patch.self as Neutron3529.ModEntry).Awake();
    }
    [Desc("废弃物判定，在开启配方乘除数时必须启用")]
    class Recipe_quantity_mult : Const {
        [Desc("废弃物判定,以竖线分割")]
        string names="Polluted|Exhaust|_Waste";
        static string[] frags;
        public override void Enable(){
            frags=names.Split('|');
        }
        public static bool IsWaste(Mafi.Core.Products.ProductProto product){
            // logwarn($"收到:{product.ToString()}, IsStorable: {product.IsStorable}, CanBeDiscarded: {product.CanBeDiscarded}, IsWaste={product.IsWaste}, IsRecyclable={product.IsRecyclable}");
            var x=product.ToString();
            return frags.Any((y)=>x.Contains(y));
        }
    }
    [Desc("建筑电力消耗最小化",-1)]
    class building_no_electric_cost : Entry {
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var ty in typeof(Mafi.Base.Prototypes.Transport.PortShapesData).Assembly.GetTypes()){
                foreach(MethodInfo i in ty.GetMethods(/*(BindingFlags)(-1)*/)){
                    if(i.Name=="RegisterData" && !i.DeclaringType.Name.Contains("Generator")){
                        yield return i;
                    }
                }
            }
        }
        static IEnumerable<CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
            vlogger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+__originalMethod.DeclaringType.Name+"的"+__originalMethod.Name+"方法");
            instructions = new CodeMatcher(instructions)
                .MatchForward(false, // false = move at the start of the match, true = move at the end of the match
                    new CodeMatch(OpCodes.Call, typeof(Mafi.ElectricityExtensions).GetMethod("Kw",new Type[]{typeof(int)}))
                    // new CodeMatch(OpCodes.Call, typeof(Mafi.Base.Prototypes.Transport.PortShapesData).GetMethod("Kw",new Type[]{typeof(int)}))
                ).Repeat( matcher => // Do the following for each match
                    matcher
                    .InsertAndAdvance(
                        new CodeInstruction(OpCodes.Pop),
                        new CodeInstruction(OpCodes.Ldc_I4_1)
                    )
                    .Advance(1) // avoid conflict.
                ).InstructionEnumeration();
            return instructions;
        }
    }

    class longer_electric_duration : Entry {
        // static Type[] assembly_types=new Type[]{typeof(Mafi.Assert), typeof(Mafi.Base.BaseMod), typeof(Mafi.Base.BaseMod), typeof(Mafi.Core.CoreMod)};
        static Assembly[] Assemblies=AppDomain.CurrentDomain.GetAssemblies();
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var ass in Assemblies){
                foreach(var ty in ass.GetTypes()){
                    if(typeof(Mafi.Core.Factory.Recipes.IRecipeForUi).IsAssignableFrom(ty)) {
                        foreach(var c in ty.GetConstructors((BindingFlags)(-1))) {
                            var counter=0;
                            foreach(var p in c.GetParameters()) {
                                if((p.Name=="duration" && p.ParameterType == typeof(Mafi.Duration)) || ( p.Name=="electricityProto" && p.ParameterType == typeof(Mafi.Core.Products.ProductProto))) {
                                    counter+=1;
                                    if(counter==2){
                                        logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                                        yield return c;break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        [Desc("电力配方持续时间乘数",10)]
        static int mult=10;
        static void Prefix(ref Mafi.Duration duration)=>duration=duration*mult;
    }
    // // [HarmonyPatch(typeof(Mafi.RecipeProtoBuilderExtensions),"AddOutput")]
    // recipes_quantity_mult是更好的选择
    // class machine_output_mult : Entry {
    //     [Desc("产量乘数")]
    //     static double factor=5;
    //     static IEnumerable<MethodBase> TargetMethods() {
    //         foreach(var ty in typeof(Mafi.Base.Prototypes.Transport.PortShapesData).Assembly.GetTypes()){
    //             foreach(MethodInfo i in ty.GetMethods(/*(BindingFlags)(-1)*/)){
    //                 if(i.Name=="RegisterData"){
    //                     yield return i;
    //                 }
    //             }
    //         }
    //     }
    //     static IEnumerable<CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
    //         logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+__originalMethod.DeclaringType.Name+"的"+__originalMethod.Name+"方法");
    //         // var from=typeof(Mafi.RecipeProtoBuilderExtensions).GetMethod("AddOutput",(BindingFlags)(-1));
    //         // var to=System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.GetMethod("AddOutput",(BindingFlags)(-1));
    //         instructions = new CodeMatcher(instructions)
    //             .MatchForward(false, // false = move at the start of the match, true = move at the end of the match
    //                 new CodeMatch(i=>i.opcode==OpCodes.Call && ((MethodBase)(i.operand)).Name == "AddOutput") // Generics
    //             ).Repeat( matcher => {// Do the following for each match
    //                 var x=((MethodInfo)(matcher.Instruction.operand)).GetGenericArguments();
    //                 if(x!=null){
    //                     var y=typeof(machine_output_mult).GetMethod("AddOutput",(BindingFlags)(-1)).MakeGenericMethod(x);
    //                     matcher.SetAndAdvance(
    //                         OpCodes.Call,y
    //                     ).Advance(1);
    //                 }
    //             }).InstructionEnumeration();
    //         return instructions;
    //     }
    //     static T AddOutput<T>(Mafi.Core.Factory.Recipes.IRecipeProtoBuilderState<T> builder, int quantity, Mafi.Core.Products.ProductProto.ID productId, string portSelector, bool outputAtStart, bool hideInUi)=>Mafi.RecipeProtoBuilderExtensions.AddOutput(builder, (int)(factor*(double)quantity), productId, portSelector, outputAtStart, hideInUi);
    // }
    class RecipeOutput_quantity_mult : Entry {
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var c in typeof(Mafi.Core.Factory.Recipes.RecipeOutput).GetConstructors((BindingFlags)(-1))){
                int counter=0;
                foreach(var p in c.GetParameters()){
                    if((p.Name=="quantity" && p.ParameterType == typeof(Mafi.Quantity)) || (p.Name=="product" && p.ParameterType == typeof(Mafi.Core.Products.ProductProto))){
                        counter++;
                        if(counter==2){
                            logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                            yield return c;break;
                        }
                    }
                }
            }
        }
        [Desc("配方产量乘除数（对废品用除法向上取整；其他用乘法）")]
        static int mult=-1;
        static void Prefix(Mafi.Core.Products.ProductProto product, ref Mafi.Quantity quantity){if(Recipe_quantity_mult.IsWaste(product)){quantity=quantity.CeilDiv(mult);}else{quantity=quantity*mult;}}
    }
    class RecipeInput_quantity_mult : Entry {
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var c in typeof(Mafi.Core.Factory.Recipes.RecipeInput).GetConstructors((BindingFlags)(-1))){
                int counter=0;
                foreach(var p in c.GetParameters()){
                    if((p.Name=="quantity" && p.ParameterType == typeof(Mafi.Quantity)) || (p.Name=="product" && p.ParameterType == typeof(Mafi.Core.Products.ProductProto))){
                        counter++;
                        if(counter==2){
                            logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                            yield return c;break;
                        }
                    }
                }
            }
        }
        [Desc("配方输入乘除数（对废品用乘法；其他用除法向上取整）")]
        static int mult=-1;
        static void Prefix(Mafi.Core.Products.ProductProto product, ref Mafi.Quantity quantity){if(Recipe_quantity_mult.IsWaste(product)){quantity=quantity*mult;}else{quantity=quantity.CeilDiv(mult);}}
    }
    class RecipeSpeed : Entry {
        // static Type[] assembly_types=new Type[]{typeof(Mafi.Assert), typeof(Mafi.Base.BaseMod), typeof(Mafi.Base.BaseMod), typeof(Mafi.Core.CoreMod)};
        static Assembly[] Assemblies=AppDomain.CurrentDomain.GetAssemblies();
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var ass in Assemblies){
                foreach(var ty in ass.GetTypes()){
                    if(typeof(Mafi.Core.Factory.Recipes.IRecipeForUi).IsAssignableFrom(ty)) {
                        foreach(var c in ty.GetConstructors((BindingFlags)(-1))) {
                            foreach(var p in c.GetParameters()) {
                                if(p.Name=="duration" && p.ParameterType == typeof(Mafi.Duration)) {
                                    logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                                    yield return c;break;
                                }
                            }
                        }
                    }
                }
            }
        }
        [Desc("配方生产速度乘数")]
        static int mult=10;
        static void Prefix(ref Mafi.Duration duration)=>duration=new Mafi.Duration((duration.Ticks+mult-1)/mult);
    }
    class truck_capacity_mult : Entry {
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var c in typeof(Mafi.Core.Vehicles.Trucks.TruckProto).GetConstructors(/*(BindingFlags)(-1)*/)){
                foreach(var p in c.GetParameters()){
                    if(p.Name=="capacity" && p.ParameterType == typeof(Mafi.Quantity)){
                        vlogger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                        yield return c;break;
                    }
                }
            }
        }
        [Desc("卡车容量乘数")]
        static int mult=100;
        static void Prefix(ref Mafi.Quantity capacity)=>capacity=capacity*mult;
    }
    class storages_capacity_mult : Entry {
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var c in typeof(Mafi.Core.Buildings.Storages.StorageBaseProto).GetConstructors((BindingFlags)(-1))){
                foreach(var p in c.GetParameters()){
                    if(p.Name=="capacity" && p.ParameterType == typeof(Mafi.Quantity)){
                        vlogger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                        yield return c;break;
                    }
                }
            }
        }
        [Desc("仓库容量乘数")]
        static int mult=200;
        static void Prefix(ref Mafi.Quantity capacity)=>capacity=capacity*mult;
    }
    class excavato_capacity_mult : Entry {
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var c in typeof(Mafi.Core.Vehicles.Excavators.ExcavatorProto).GetConstructors(/*(BindingFlags)(-1)*/)){
                foreach(var p in c.GetParameters()){
                    if(p.Name=="capacity" && p.ParameterType == typeof(Mafi.Quantity)){
                        logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                        yield return c;break;
                    }
                }
            }
        }
        [Desc("挖掘机容量乘数")]
        static int mult=200;
        static void Prefix(ref Mafi.Quantity capacity)=>capacity=capacity*mult;
    }
    [HarmonyPatch(typeof(Mafi.Core.Buildings.ResearchLab.ResearchLabProtoBuilder.State),"SetResearchSpeed")]
    class ResearchSpeed_mult : Entry {
        [Desc("研究产出乘数")]
        static int mult=1000;
        [Desc("研究产出速度")]
        static int speed=10;
        static void Prefix(ref Mafi.Duration duration, ref Mafi.Fix32 stepsPerDuration){
            stepsPerDuration=stepsPerDuration*mult;
            duration=new Mafi.Duration((duration.Ticks+speed-1)/speed);
        }
    }
    class TreePlanterSpeed_mult : Entry {
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var c in typeof(Mafi.Core.Vehicles.TreePlanters.TreePlanterProto.Timings).GetConstructors((BindingFlags)(-1))){
                foreach(var p in c.GetParameters()){
                    if(p.ParameterType == typeof(Mafi.Duration)){
                        logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                        yield return c;break;
                    }
                }
            }
        }
        [Desc("植树机速度")]
        static int speed=10;
        static void Prefix(ref Mafi.Duration plantingDuration, ref Mafi.Duration returningToIdleDuration){
            plantingDuration=new Mafi.Duration((plantingDuration.Ticks+speed-1)/speed);
            returningToIdleDuration=new Mafi.Duration((returningToIdleDuration.Ticks+speed-1)/speed);
        }
    }
    class ExcavatorSpeed_mult : Entry {
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var c in typeof(Mafi.Core.Vehicles.Excavators.ExcavatorProto.Timings).GetConstructors((BindingFlags)(-1))){
                foreach(var p in c.GetParameters()){
                    if(p.ParameterType == typeof(Mafi.Duration)){
                        logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                        yield return c;break;
                    }
                }
            }
        }
        [Desc("挖掘机速度")]
        static int speed=10;
        static void Prefix(ref Mafi.Duration prepareToMineDuration, ref Mafi.Duration mineDuration, ref Mafi.Duration prepareToDumpDuration, ref Mafi.Duration dumpDuration, ref Mafi.Duration dumpDelay, ref Mafi.Duration mineIterationDuration){
            prepareToMineDuration=new Mafi.Duration((prepareToMineDuration.Ticks+speed-1)/speed);
            mineDuration=new Mafi.Duration((mineDuration.Ticks+speed-1)/speed);
            prepareToDumpDuration=new Mafi.Duration((prepareToDumpDuration.Ticks+speed-1)/speed);
            dumpDuration=new Mafi.Duration((dumpDuration.Ticks+speed-1)/speed);
            dumpDelay=new Mafi.Duration((dumpDelay.Ticks+speed-1)/speed);
            mineIterationDuration=new Mafi.Duration((mineIterationDuration.Ticks+speed-1)/speed);
        }
    }

    [Desc("挖掘机深度修正")]
    [HarmonyPatch(typeof(Mafi.Core.Entities.Dynamic.ExcavatorProtoBuilder.ExcavatorProtoBuilderState),"SetMinedThicknessByDistanceMeters")]
    class ExcavatorthicknessMeters_mult : Entry {
        static void Prefix(ref float[] thicknessMeters){
            thicknessMeters=new float[thicknessMeters.Length*2];
            for(int i=0;i<thicknessMeters.Length;i++){
                thicknessMeters[i]=20f;
            }
        }
    }
    class TreeHarvestSpeed_mult : Entry {
        static IEnumerable<MethodBase> TargetMethods(MethodBase original) {
            foreach(var c in typeof(Mafi.Core.Vehicles.TreeHarvesters.TreeHarvesterProto.Timings).GetConstructors((BindingFlags)(-1))){
                foreach(var p in c.GetParameters()){
                    if(p.ParameterType == typeof(Mafi.Duration)){
                        logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                        yield return c;break;
                    }
                }
            }
        }
        [Desc("伐木速度")]
        static int speed=10;
        static void Prefix(ref Mafi.Duration toPrepareForHarvestDuration, ref Mafi.Duration toTreeLayingDownDuration, ref Mafi.Duration toTreeAboveTruckDuration, ref Mafi.Duration toTreeOnTruckDuration, ref Mafi.Duration toArmUpDuration, ref Mafi.Duration toFoldedDuration, ref Mafi.Duration cuttingDuration, ref Mafi.Duration trimmingDuration, ref Mafi.Duration moveToNextSectionDuration, ref Mafi.Duration cutNextSectionDuration){
            toPrepareForHarvestDuration=new Mafi.Duration((toPrepareForHarvestDuration.Ticks+speed-1)/speed);
            toTreeLayingDownDuration=new Mafi.Duration((toTreeLayingDownDuration.Ticks+speed-1)/speed);
            toTreeAboveTruckDuration=new Mafi.Duration((toTreeAboveTruckDuration.Ticks+speed-1)/speed);
            toTreeOnTruckDuration=new Mafi.Duration((toTreeOnTruckDuration.Ticks+speed-1)/speed);
            toArmUpDuration=new Mafi.Duration((toArmUpDuration.Ticks+speed-1)/speed);
            toFoldedDuration=new Mafi.Duration((toFoldedDuration.Ticks+speed-1)/speed);
            cuttingDuration=new Mafi.Duration((cuttingDuration.Ticks+speed-1)/speed);
            trimmingDuration=new Mafi.Duration((trimmingDuration.Ticks+speed-1)/speed);
            moveToNextSectionDuration=new Mafi.Duration((moveToNextSectionDuration.Ticks+speed-1)/speed);
            cutNextSectionDuration=new Mafi.Duration((cutNextSectionDuration.Ticks+speed-1)/speed);
        }
    }
    // [HarmonyPatch(typeof(Mafi.Core.Buildings.Farms.Farm),"getNaturalReplenishPerDayAt")]
    // class Farm_getNaturalReplenishPerDayAt : Entry {
    //     [Desc("农场肥力平衡目标百分比")]
    //     static int percentage=1000;
    //     public override void Enable(){
    //         Target=Mafi.Percent.One*percentage;
    //         base.Enable();
    //     }
    //     static Mafi.Percent Target=Mafi.Percent.One;
    //     static bool Prefix(Mafi.Percent __result, Mafi.Percent fertility, Mafi.Core.Buildings.Farms.Farm __instance){
    //         var result = (Target - fertility) * __instance.Prototype.FertilityReplenishPerDay;
    //         if (result.IsNegative) {
    //             return result.ScaleBy(Mafi.Core.Buildings.Farms.Farm.FERTILITY_REPLENISH_MULT_WHEN_ABOVE_100);
    //         } else {
    //             return result;
    //         }
    //     }
    // }
    class farm_yield_mult : Entry {
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var c in typeof(Mafi.Core.Buildings.Farms.FarmProto).GetConstructors((BindingFlags)(-1))){
                var counter=0;
                foreach(var p in c.GetParameters()){
                    if((p.Name=="waterEvaporationPerDay" && p.ParameterType == typeof(Mafi.PartialQuantity)) || (p.Name=="yieldMultiplier" &&  p.ParameterType == typeof(Mafi.Percent))){
                        counter++;
                        if(counter==2){
                            vlogger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                            yield return c;break;
                        }
                    }
                }
            }
        }
        [Desc("水蒸发速率除数")]
        static int wmult=100;
        [Desc("农田产出乘数")]
        static int ymult=10;
        static Mafi.PartialQuantity we=Mafi.PartialQuantity.Epsilon;
        public override void Enable(){
            we=Mafi.PartialQuantity.Epsilon*(wmult-1); // 向上取整除
            base.Enable();
        }
        static void Prefix(ref Mafi.PartialQuantity waterEvaporationPerDay, ref Mafi.Percent yieldMultiplier){
            waterEvaporationPerDay=(waterEvaporationPerDay+we)/wmult;
            yieldMultiplier=yieldMultiplier*ymult;
        }
    }
    class FuelTankProto_mod : Entry {
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var c in typeof(Mafi.Core.Entities.Dynamic.FuelTankProto).GetConstructors((BindingFlags)(-1))){
                foreach(var p in c.GetParameters()){
                    if(p.Name == "duration" && p.ParameterType == typeof(Mafi.Duration)){
                        logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                        yield return c;break;
                    }
                }
            }
        }
        [Desc("车辆油耗除数")]
        static int div=10;
        static void Prefix(ref Mafi.Duration duration)=>duration=duration*div;
    }
    class SettlementFoodModuleProto_mod : Entry {
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var c in typeof(Mafi.Core.Buildings.Settlements.SettlementFoodModuleProto).GetConstructors((BindingFlags)(-1))){
                foreach(var p in c.GetParameters()){
                    if(p.Name == "capacityPerBuffer" && p.ParameterType == typeof(Mafi.Quantity)){
                        logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                        yield return c;break;
                    }
                }
            }
        }
        [Desc("定居点食物容量乘数")]
        static int mul=10;
        static void Prefix(ref Mafi.Quantity capacityPerBuffer)=>capacityPerBuffer=capacityPerBuffer*mul;
    }
    class FoodProto_mod : Entry {
        static IEnumerable<MethodBase> TargetMethods() {
            foreach(var c in typeof(Mafi.Core.Population.FoodProto).GetConstructors((BindingFlags)(-1))){
                var counter=0;
                foreach(var p in c.GetParameters()){
                    if((p.Name == "consumedPerHundredPopsPerMonth" && p.ParameterType == typeof(Mafi.Fix32)) || (p.Name=="upointsWhenProvided" && p.ParameterType == typeof(Mafi.Upoints))){
                        counter++;
                        if(counter==2){
                            logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
                            yield return c;break;
                        }
                    }
                }
            }
        }
        [Desc("食物消耗除数")]
        static int div=10;
        [Desc("食物凝聚点倍数")]
        static int mul=10;
        static void Prefix(ref Mafi.Fix32 consumedPerHundredPopsPerMonth, ref Mafi.Upoints upointsWhenProvided){
            consumedPerHundredPopsPerMonth=(consumedPerHundredPopsPerMonth+(div-1))/div;
            upointsWhenProvided*=mul;
        }
    }
    // class DrivingData_mod : Entry {
    //     static IEnumerable<MethodBase> TargetMethods() {
    //         foreach(var c in typeof(Mafi.Core.Entities.Dynamic.DrivingData).GetConstructors((BindingFlags)(-1))){
    //             foreach(var p in c.GetParameters()){
    //                 if(p.Name == "maxForwardsSpeed" && p.ParameterType == typeof(Mafi.RelTile1f)){
    //                     logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
    //                     yield return c;break;
    //                 }
    //             }
    //         }
    //     }
    //     [Desc("车辆速度乘数")]
    //     static int mul=10;
    //     static void Prefix(ref Mafi.RelTile1f maxForwardsSpeed, ref Mafi.RelTile1f maxBackwardsSpeed, ref Mafi.RelTile1f acceleration, ref Mafi.RelTile1f breaking, ref Mafi.AngleDegrees1f maxSteeringAngle, ref Mafi.AngleDegrees1f maxSteeringSpeed){
    //         maxForwardsSpeed=maxForwardsSpeed*mul;
    //         maxBackwardsSpeed=maxBackwardsSpeed*mul;
    //         acceleration=acceleration*mul;
    //         breaking=breaking*mul;
    //         maxSteeringAngle=maxSteeringAngle*mul;
    //         maxSteeringSpeed=maxSteeringSpeed*mul;
    //     }
    // }
    // class SmoothDriverSpeed_mult : Entry {
    //     static IEnumerable<MethodBase> TargetMethods() {
    //         foreach(var c in typeof(Mafi.Core.Entities.Dynamic.SmoothDriver).GetConstructors((BindingFlags)(-1))){
    //             foreach(var p in c.GetParameters()){
    //                 if(p.ParameterType == typeof(Mafi.Fix32)){
    //                     logger("%%PLUGIN_ID%%-类"+System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.DeclaringType.Name+"正在注入类别"+c.DeclaringType.Name+"的"+c.Name+"方法");
    //                     yield return c;break;
    //                 }
    //             }
    //         }
    //     }
    //     [Desc("车辆前进速度")]
    //     static double fspeed=2;
    //     [Desc("车辆后退速度")]
    //     static double bspeed=3;
    //     [Desc("车辆加速度")]
    //     static double aspeed=10;
    //     [Desc("车辆刹车速度")]
    //     static double sspeed=10;
    //     static void Prefix(ref Mafi.Fix32 maxForwardsSpeed, ref Mafi.Fix32 maxBackwardsSpeed, ref Mafi.Fix32 maxAcceleration, ref Mafi.Fix32 maxBraking/*, ref Mafi.Fix32 brakingConservativeness*/){
    //         maxForwardsSpeed = Mafi.Fix32.FromDouble(maxForwardsSpeed.ToDouble()*fspeed);
    //         maxBackwardsSpeed = Mafi.Fix32.FromDouble(maxBackwardsSpeed.ToDouble()*bspeed);
    //         maxAcceleration = Mafi.Fix32.FromDouble(maxAcceleration.ToDouble()*aspeed);
    //         maxBraking = Mafi.Fix32.FromDouble(maxBraking.ToDouble()*sspeed);
    //     }
    // }
}
